package com.dave.gd.common.redis.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.springframework.util.SerializationUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import com.dave.gd.common.exception.CacheException;
import com.dave.gd.common.redis.ICacheRepository;
import com.dave.gd.common.util.BinaryUtil;

public class RedisProxyRepositoryImpl implements ICacheRepository {
    
    private JedisPool pool;
    
    /**
     * .
     * 构造方法
     * 
     * @author zhenglincheng
     *         2014年11月14日 zhenglincheng
     */
    public RedisProxyRepositoryImpl() {
        super();
    }
    
    /**
     * .
     * 构造方法
     * 
     * @param pool
     * @author zhenglincheng
     *         2014年11月14日 zhenglincheng
     */
    public RedisProxyRepositoryImpl(final JedisPool pool) {
        super();
        this.pool = pool;
    }
    
    @Override
    public boolean keyExists(final String group, final String key) {
        final Jedis client = this.getClient();
        final boolean r = client.exists((group + key).getBytes());
        this.returnClient(client);
        return r;
    }
    
    @Override
    public String rename(final String group, final String oldkey, final String newkey) {
        final Jedis client = this.getClient();
        byte[] b = client.get((group + oldkey).getBytes());
        String r = null;
        if (null != b) {
            client.del((group + oldkey).getBytes());
            r = client.set((group + oldkey).getBytes(), b);
        }
        this.returnClient(client);
        return r;
    }
    
    @Override
    public Long delete(final String group, String... keys) {
        final Jedis client = this.getClient();
        final Long r = client.del(BinaryUtil.StringToBinary(group, keys));
        this.returnClient(client);
        return r;
    }
    
    @Override
    public Long expire(final String group, final String key, final int seconds) {
        final Jedis client = this.getClient();
        final Long r = client.expire((group + key).getBytes(), seconds);
        this.returnClient(client);
        return r;
    }
    
    @Override
    public Long ttl(final String group, final String key) {
        final Jedis client = this.getClient();
        final Long r = client.ttl((group + key).getBytes());
        this.returnClient(client);
        return r;
    }
    
    @Override
    public Long persist(final String group, final String key) {
        final Jedis client = this.getClient();
        final Long r = client.persist((group + key).getBytes());
        this.returnClient(client);
        return r;
    }
    
    @Override
    public String set(final String group, final String key, final String value) {
        final Jedis client = this.getClient();
        final String r = client.set((group + key), value);
        this.returnClient(client);
        return r;
    }
    
    @Override
    public String set(final String group, final String key, final String value, final int seconds) {
        final Jedis client = this.getClient();
        final String r = client.set((group + key), value);
        client.expire((group + key), seconds);
        this.returnClient(client);
        return r;
    }
    
    @Override
    public List<String> getMulti(String group, String... keys) {
        String[] newKeys = new String[keys.length];
        for (int i = 0; i < keys.length; i++) {
            newKeys[i] = group + keys[i];
        }
        final Jedis client = this.getClient();
        final List<String> result = client.mget(newKeys);
        this.returnClient(client);
        return result;
    }
    
    @Override
    public String get(String group, String key) {
        final Jedis client = this.getClient();
        final String r = client.get((group + key));
        this.returnClient(client);
        return r;
    }
    
    @Override
    public Object getObject(String group, String key) {
        final Jedis client = this.getClient();
        final byte[] b = client.get((group + key).getBytes());
        this.returnClient(client);
        Object obj;
        obj = SerializationUtils.deserialize(b);
        if (null != obj) {
            return obj;
        }
        return new String(b);
    }
    
    @Override
    public List<?> getMultiObject(String group, String... keys) {
        
        final Jedis client = this.getClient();
        final List<byte[]> res = client.mget(BinaryUtil.StringToBinary(group, keys));
        this.returnClient(client);
        final List<Object> result = new ArrayList<Object>();
        for (int i = 0; i < res.size(); i++) {
            Object obj;
            obj = SerializationUtils.deserialize(res.get(i));
            if (null != obj) {
                result.add(obj);
            } else {
                result.add(new String(res.get(i)));
            }
            
        }
        return result;
    }
    
    @Override
    public String setObject(String group, String key, final Serializable value, final int seconds) {
        final Jedis client = this.getClient();
        String r = null;
        r = client.set((group + key).getBytes(), SerializationUtils.serialize(value));
        client.expire((group + key).getBytes(), seconds);
        this.returnClient(client);
        return r;
    }
    
    @Override
    public String setObject(String group, String key, final Serializable value) {
        final Jedis client = this.getClient();
        String r = null;
        r = client.set((group + key).getBytes(), SerializationUtils.serialize(value));
        this.returnClient(client);
        return r;
    }
    
    public void setPool(final JedisPool pool) {
        this.pool = pool;
    }
    
    private Jedis getClient() {
        try {
            return this.pool.getResource();
        } catch (final Exception e) {
            throw new CacheException("Redis get connect exception");
        }
    }
    
    private void returnClient(final Jedis client) {
        try {
            this.pool.returnResource(client);
        } catch (final Exception e) {
            throw new CacheException("Redis can not resource connection!");
        }
    }
    
}
